﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_VECTOR_H
#define _UXS_VECTOR_H

#pragma once

#include "MathFunc.h"
#include "MathTypes.h"
#include "../Containers/TString.h"

namespace UX_STL
{
namespace UXMath
{

	
#	define VEC_UN_OPERATOR( _op ) \
		\
		const Self	operator _op () const \
		{ \
			Self	ret; \
			FOR( i, *this )	 ret[i] = _op (*this)[i]; \
			return ret; \
		}


#	define VEC_BIN_OPERATOR( _op ) \
		Self &		operator _op##= (const Self& right) \
		{ \
			FOR( i, *this )	 (*this)[i] _op##= right[i]; \
			return *this; \
		} \
		const Self	operator _op  (const Self& right) const \
		{ \
			Self	ret; \
			FOR( i, *this )	 ret[i] = ( (*this)[i] _op right[i] ); \
			return ret; \
		} \
		Self &		operator _op##= (const T& right) \
		{ \
			FOR( i, *this )	 (*this)[i] _op##= right; \
			return *this; \
		} \
		const Self	operator _op  (const T& right) const \
		{ \
			Self	ret; \
			FOR( i, *this )	 ret[i] = ( (*this)[i] _op right ); \
			return ret; \
		} \
		friend const Self operator _op (const T& left, const Self& right) \
		{ \
			return Self(left) _op right; \
		}

#	define VEC_BIN_OPERATOR2( _op ) \
		\
		Self	operator _op  (const T& right) const \
		{ \
			Self	ret; \
			FOR( i, *this )	 ret[i] = ( (*this)[i] _op right ); \
			return ret; \
		} \
		\
		Self	operator _op  (const Self& right) const \
		{ \
			Self	ret; \
			FOR( i, *this )	 ret[i] = ( (*this)[i] _op right[i] ); \
			return ret; \
		} \
		\
		friend Self operator _op (const T& left, const Self& right) \
		{ \
			return Self(left) _op right; \
		}


	
#define I	1
#include "TVecI.h"
#undef	I


#define I	2
#include "TVecI.h"
#undef	I

	
#define I	3
#include "TVecI.h"
#undef	I


#define I	4
#include "TVecI.h"
#undef	I

	

	template <typename T>
	inline TVec<T,3> Cross (const TVec<T,3> &left, const TVec<T,3> &right)
	{
		return TVec<T,3>(	left.y * right.z - right.y * left.z,
							left.z * right.x - right.z * left.x,
							left.x * right.y - right.x * left.y );
	}

	
	template <typename T>
	inline T Cross (const TVec<T,2> &left, const TVec<T,2> &right)
	{
		return left.x * right.y - left.y * right.x;
	}


	template <typename T, usize I>
	inline T  Dot (const TVec<T,I> &left, const TVec<T,I> &right)
	{
		return left.Dot( right );
	}



	template <typename T, usize I>
	struct UX_STL::UXTypes::TypeInfo < UXMath::TVec<T,I> >
	{
	private:
		typedef UXTypes::TypeInfo<T>	_value_type_info;

	public:
		typedef UXMath::TVec<T,I>	type;
		typedef type				inner_type;
		typedef T					value_type;

		// similar types //
		typedef UXMath::TVec< typename _value_type_info::Similar_Unsigned, I >	Similar_Unsigned;
		typedef UXMath::TVec< typename _value_type_info::Similar_Signed, I >	Similar_Signed;
		typedef UXMath::TVec< typename _value_type_info::Similar_Float, I >		Similar_Float;
		typedef UXMath::TVec< typename _value_type_info::Similar_UInt, I >		Similar_UInt;
		typedef UXMath::TVec< typename _value_type_info::Similar_Int, I >		Similar_Int;

		// type descriptor //
		enum {
			FLAGS	= (int)_value_type_info::FLAGS | (int)UX_STL::UXTypes::_ctime_hidden_::VECTOR,
			UID		= __COUNTER__,
		};

		static constexpr type			Max()		{ return type( _value_type_info::Max() ); }
		static constexpr type			Min()		{ return type( _value_type_info::Min() ); }
		static			 type			Inf()		{ return type( _value_type_info::Inf() ); }
		static			 type			NaN()		{ return type( _value_type_info::NaN() ); }
		
		static constexpr type			Epsilon()	{ return type( _value_type_info::Epsilon() ); }
		static constexpr uint			SignBit()	{ return _value_type_info::SignBit(); }
		
		static const char *				Name()		{ return "Vec"; }

		_CHECK_SIMILAR_TYPES();
	};


#	undef	VEC_UN_OPERATOR
#	undef	VEC_BIN_OPERATOR

//-------------------------------------------------------------------

}	// UXMath
}	// UX_STL

#endif	// _UXS_VECTOR_H